package com.wdl.modules.myhouse.service.impl;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wdl.modules.myhouse.common.Result;
import com.wdl.modules.myhouse.dao.FileDao;
import com.wdl.modules.myhouse.entity.FileDescEntity;
import com.wdl.modules.myhouse.entity.FileEntity;
import com.wdl.modules.myhouse.entity.FileTypeEntity;
import com.wdl.modules.myhouse.service.FileDescService;
import com.wdl.modules.myhouse.service.FileService;

import com.wdl.modules.myhouse.service.FileTypeService;
import com.wdl.modules.myhouse.common.MyPage;
import com.wdl.modules.myhouse.spider.CategoryFileSpider;
import com.wdl.modules.myhouse.utils.util.DateUtil;
import com.wdl.modules.myhouse.utils.util.JsonUtil;
import com.wdl.modules.myhouse.utils.util.MathUtils;
import com.wdl.modules.myhouse.utils.util.PageUtil;
import com.wdl.modules.myhouse.vo.FileVo;
import com.wdl.modules.myhouse.vo.spider.FileSpider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


/**
 * 文件表
 *
 * @author lucain sunlightcs@gmail.com
 * @since 1.0.0 2022-08-13
 */
@Service
@Slf4j
public class FileServiceImpl extends ServiceImpl<FileDao, FileEntity> implements FileService {


    @Autowired
    private FileTypeService fileTypeService;
    @Autowired
    private FileDao fileDao;
    @Autowired
    private FileDescService fileDescService;
    @Autowired
    private CategoryFileSpider runSpider;
    @Autowired
    private ThreadPoolExecutor pool;


    @Override
    public IPage<FileVo> getAllFileVo(MyPage pageParam, String cat) {
        if (cat != null && !cat.isEmpty()) {
            FileTypeEntity typeEntity = fileTypeService.getOne(new QueryWrapper<FileTypeEntity>().lambda().eq(FileTypeEntity::getSourceTypeName, cat));
            if (typeEntity != null) {
                return getFileVos(pageParam,new QueryWrapper<FileEntity>().lambda().eq(FileEntity::getFileTypeId, typeEntity.getId()));
            }
        }
        return getFileVos(pageParam, new QueryWrapper<FileEntity>());
    }

    @Override
    public IPage<FileVo> getFileByKeyWord(String keyWord, MyPage page1) {
        LambdaQueryWrapper<FileEntity> wrapper = new QueryWrapper<FileEntity>().lambda()
                .like(FileEntity::getFileDescribe, keyWord).or()
                .like(FileEntity::getFileName, keyWord).or()
                .like(FileEntity::getFileTag, keyWord);
        return getFileVos(page1, wrapper);
    }

    @Override
    public Map<String, Integer> staticByDay(Integer year, Integer month) {
        //  此处需要手动拼个串 %Y-%m
        if (month < 10) {
            return fileDao.selectFileNumByUploadTime(year + "-0" + month);
        } else {
            return fileDao.selectFileNumByUploadTime(year + "-" + month);
        }

    }

    @Override
    public Map<String, Integer> downLoadstatisticByDay(Integer year, Integer month) {
        if (month < 10) {
            return fileDao.downLoadStatistic(year + "-0" + month);
        } else {
            return fileDao.downLoadStatistic(year + "-" + month);
        }
    }

    /**
     * todo 数据的增量更新
     */
    @Override
    @Async
    public Result<String> saveSpiderData() {
        Map<String, Integer> catName2id = fileTypeService.list().stream().collect(Collectors.toMap(FileTypeEntity::getSourceTypeName, FileTypeEntity::getId));
        ArrayList<FileDescEntity> descEntities = new ArrayList<>();
        ArrayList<FileEntity> fileEntities = new ArrayList<>();
        try {
            DateUtil.startTimer();
            List<FileSpider> spiderFiles = runSpider.runAsync();
            DateUtil.stopTimer("爬取数据共花费:");
            DateUtil.startTimer();
            log.info("开始保存数据");
            for (FileSpider fileSpider : spiderFiles) {

                FileEntity fileEntity = new FileEntity();
                FileDescEntity fileDescEntity = new FileDescEntity();
                //构建fileEntity对象
                BeanUtils.copyProperties(fileSpider, fileEntity);
                Long fileId = MathUtils.randomLong();
//                fileEntity.setId(fileId);
                fileEntity.setFileTypeId(catName2id.get(fileSpider.getFileTypeName()) == null ? 92 : catName2id.get(fileSpider.getFileTypeName()));
                fileEntity.setFileDescribe(fileSpider.getArticleTitle());
                fileEntity.setFileTag("正在使用");
                fileEntity.setFileUrl(fileSpider.getSourceLink());
                fileEntity.setImgUrl(fileSpider.getTitleImgUrl());
                fileEntities.add(fileEntity);

                //构建fileDesc对象
                BeanUtils.copyProperties(fileSpider, fileDescEntity);
                Set<String> downloadLinks = fileSpider.getDownloadLinks();
                Object[] links = downloadLinks.toArray();
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < links.length; i++) {
                    if (i != downloadLinks.size() - 1) {
                        builder.append(links[i] + ",");
                    } else {
                        builder.append(links[i]);
                    }
                }

                fileDescEntity.setDownloadLinks(builder.toString());
//                fileDescEntity.setFileId(fileEntity.getId());
                descEntities.add(fileDescEntity);
            }
            Long index = 0L;
            for (int i = 0; i < fileEntities.size(); i++) {
                fileEntities.get(i).setId(index);
                descEntities.get(i).setFileId(index);
                index++;
            }

            pool.submit(() -> {
                try {
                    saveObject(JsonUtil.obj2String(fileEntities), "G:\\spider.txt");
                    saveObject(JsonUtil.obj2String(descEntities), "G:\\spider1.txt");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });

            this.saveBatch(fileEntities);
            fileDescService.saveBatch(descEntities);
            log.info("数据保存完成,共计: " + fileEntities.size() + "条");
            DateUtil.stopTimer("保存数据共花费:");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new Result<String>();
    }

    /**
     * 保存爬取专题类数据
     * @param
     * @return
     */
    @Override
    @Async
    @Transactional
    public Result<String> saveSpiderTopicRes() {
        ArrayList<FileDescEntity> descEntities = new ArrayList<>();
        ArrayList<FileEntity> fileEntities = new ArrayList<>();
        try {
            DateUtil.startTimer();
            List<FileSpider> spiderFiles = runSpider.spiderTopicRes();
            DateUtil.stopTimer("爬取数据共花费:");
            DateUtil.startTimer();
            log.info("开始保存数据");
            for (FileSpider fileSpider : spiderFiles) {
                FileEntity fileEntity = new FileEntity();
                FileDescEntity fileDescEntity = new FileDescEntity();
                //构建fileEntity对象
                BeanUtils.copyProperties(fileSpider, fileEntity);
                int typeId;
                switch (fileSpider.getFileTypeName()){
                    case "修改软件":
                        typeId=93;
                        break;
                    case "惊奇软件":
                        typeId=94;
                        break;
                    case "软件合集":
                        typeId=95;
                        break;
                    case "帮助文档":
                        typeId=96;
                        break;
                    case "开源软件":
                        typeId=97;
                        break;
                    default:
                        typeId=59;
                }
                fileEntity.setFileTypeId(typeId);
                fileEntity.setFileDescribe(fileSpider.getArticleTitle());
                fileEntity.setFileTag("正在使用");
                fileEntity.setFileUrl("/softDetailSpider");
                fileEntity.setImgUrl(fileSpider.getTitleImgUrl());
                fileEntities.add(fileEntity);

                //构建fileDesc对象
                BeanUtils.copyProperties(fileSpider, fileDescEntity);
                Set<String> downloadLinks = fileSpider.getDownloadLinks();
                Object[] links = downloadLinks.toArray();
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < links.length; i++) {
                    if (i != downloadLinks.size() - 1) {
                        builder.append(links[i] + ",");
                    } else {
                        builder.append(links[i]);
                    }
                }

                fileDescEntity.setDownloadLinks(builder.toString());
                descEntities.add(fileDescEntity);
            }
            Long index = 10337L;
            for (int i = 0; i < fileEntities.size(); i++) {
                fileEntities.get(i).setId(index);
                descEntities.get(i).setFileId(index);
                index++;
            }

//            pool.submit(() -> {
//                try {
//                    saveObject(JsonUtil.obj2String(fileEntities), "G:\\spider.txt");
//                    saveObject(JsonUtil.obj2String(descEntities), "G:\\spider1.txt");
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            });

            this.saveBatch(fileEntities);
            fileDescService.saveBatch(descEntities);
            log.info("数据保存完成,共计: " + fileEntities.size() + "条");
            DateUtil.stopTimer("保存数据共花费:");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return new Result<String>();
    }





    @Override
    public FileVo getFileDetailById(Long id) {
        return this.baseMapper.getFileDetailById(id);
    }

    private void saveObject(String json, String path) throws IOException {

        if (!new File(path).exists()) {
            new File(path).createNewFile();
        }
        FileOutputStream outputStream = new FileOutputStream(path);
        outputStream.write(json.getBytes(StandardCharsets.UTF_8));
        outputStream.close();
    }

    private IPage<FileVo> getFileVos(MyPage page1, Wrapper<FileEntity> wrapper) {
        Map<Integer, FileTypeEntity> typeId2Entity = fileTypeService.list(new QueryWrapper<FileTypeEntity>()).stream().collect(Collectors.toMap(FileTypeEntity::getId, par -> par));
        IPage<FileEntity> page = this.baseMapper.selectPage(PageUtil.getIPage(page1, new FileEntity()), wrapper);
        List<FileEntity> records = page.getRecords();
        List<FileVo> voArrayList = new ArrayList<FileVo>();
        if (records != null) {
            voArrayList = records.stream().map(record -> {
                FileVo vo = new FileVo();
                BeanUtils.copyProperties(record, vo);
                vo.setFileTypeName(typeId2Entity.get(vo.getFileTypeId()).getTypeName());
                return vo;
            }).collect(Collectors.toList());
        }
        IPage<FileVo> page2 = new Page<>();
        BeanUtils.copyProperties(page, page2);
        page2.setRecords(voArrayList);
        return page2;
    }

}